#include "Aimbot.h"

Aimbot g_pAimbot;

void Aimbot::DropTarget()
{
	vFinal	   = SD_Tools::Vector();
	m_iTarget  = -1;
	m_flDistance = 999999999.9f;
}

void Aimbot::Init()
{
	TargetBone = BONE_HEAD;
	vFinal = SD_Tools::Vector();
	m_iTarget = -1;
	m_flDistance = 999999999.9f;
	Active = false;
	Silent = false;
	LegitSpeed = false;
	MaxSpeed = 3.0f;
	TickSpeed = 0.1f;
	LegitFov = false;
	Fov = 50.0f;
}

void Aimbot::Enable()
{
	Active = true;
}

void Aimbot::Disable()
{
	Active = false;
}

void Aimbot::Set( bool Active )
{
	this->Active = Active;
}

void Aimbot::SetBone( int Bone )
{
	TargetBone = Bone;
}

bool Aimbot::Compute( CUserCmd* cmd )
{
	static float CurSpeed = 0.0f;
	if (!Active)
	{
		return false;
	}
	player_info_t pinfo;
	SD_Tools::Vector vPlayer;

	if(!GameUtilities::HasGun())
		return false;

	DropTarget();

	int LocalPlayerIndex = g_pInterfaces.g_pEngine->GetLocalPlayer();
	Entity* pMe = g_pInterfaces.g_pEntList->GetClientEntity(LocalPlayerIndex);
	if (!pMe)
	{
		return false;
	}

	if (pMe->iTeamNum() == TeamSpec)
	{
		return false;
	}

	CBaseCombatWeapon* pWeapon = GameUtilities::GetBaseCombatWeapon(pMe);

	if(!pWeapon || !pWeapon->IsReady())
	{
		return false;
	}

	SD_Tools::Vector m_Eye = pMe->GetEyePosition();

	GameUtilities::Predict(pMe, m_Eye, 3.f);

	int MaxEntities = g_pInterfaces.g_pEntList->GetHighestEntityIndex();

	float dmg;
	SD_Tools::Vector CurrentVec;
	//SD_Tools::Angle ViewAngle = cmd->viewangles;
	SD_Tools::Angle ViewAngle;
	g_pInterfaces.g_pEngine->GetViewAngles(&ViewAngle);
	ViewAngle.ToVectors_s(&CurrentVec, NULL, NULL);

	for(int i = 1; i < MaxEntities; ++i)
	{
		Entity* baseEntity = g_pInterfaces.g_pEntList->GetClientEntity(i);

		if(i == LocalPlayerIndex || baseEntity == NULL || *baseEntity->dormant() || baseEntity == pMe || *baseEntity->lifeState() != 0 /*LIFE_ALIVE*/ || !g_pInterfaces.g_pEngine->GetPlayerInfo(i, &pinfo) || *baseEntity->iTeamNum() == *pMe->iTeamNum() || !baseEntity->GetBone(TargetBone, &vPlayer) || /*!g_pAutowall.isHittable(vPlayer, baseEntity, dmg)*/!GameUtilities::IsVisible(m_Eye, vPlayer, pMe, baseEntity))
			continue;
		float m_Dist = SD_Tools::MathHelper::DistanceVector(m_Eye, vPlayer);
		if (LegitFov)
		{
			SD_Tools::Vector TempVec = vPlayer;
			TempVec.z += 8.0f;

			TempVec.Subtract(m_Eye);

			float TempFloat = GameUtilities::GetAngleBetween(CurrentVec, TempVec);
			if (TempFloat > Fov/2)
			{
				continue;
			}
		}
		if(m_flDistance < m_Dist)
			continue;
		m_flDistance =  m_Dist;
		m_iTarget = i;
		vFinal = vPlayer;
		vFinal.z += 8.0f;
		GameUtilities::Predict(baseEntity, vFinal, 5.f);
	}
	if(m_iTarget == -1)
	{
		return false;
	}
	if(!Silent)
	{
		if (LegitSpeed)
		{

			SD_Tools::Vector TempVec = vFinal;
			TempVec.Subtract(m_Eye);

			float NeededAngleFl = GameUtilities::GetAngleBetween(CurrentVec, TempVec);
			SD_Tools::Angle FinalAngle = GameUtilities::CreateAimAngle(m_Eye, vFinal);
			FinalAngle.x -= pMe->getRecoilVec()->x*2;
			FinalAngle.y -= pMe->getRecoilVec()->y*2;
			printf("CurSpeed: %.02f\nNeededAngle: %.02f\n\n", CurSpeed, NeededAngleFl);
			if (CurSpeed < NeededAngleFl)
			{
				SD_Tools::Angle CurAngle = cmd->viewangles;
				SD_Tools::Angle TempAngle = FinalAngle;

				float Temp = CurSpeed / NeededAngleFl;

				TempAngle.Subtract(CurAngle);
				TempAngle.Multiply(Temp);

				CurAngle.Add(TempAngle);

				FinalAngle = CurAngle;

				cmd->viewangles = FinalAngle;
				g_pInterfaces.g_pEngine->SetViewAngles(FinalAngle);

				if (CurSpeed < MaxSpeed)
				{
					CurSpeed += TickSpeed;
				}
				return true;
			}
			CurSpeed = 0.0f;
			cmd->buttons |= IN_ATTACK;
			cmd->viewangles = FinalAngle;
			g_pInterfaces.g_pEngine->SetViewAngles(FinalAngle);
			return true;
		}
		else
		{
			cmd->buttons |= IN_ATTACK;
			cmd->viewangles = GameUtilities::CreateAimAngle(m_Eye, vFinal);
			return true;
		}
	}

	SD_Tools::Vector viewforward, viewright, viewup, aimforward, aimright, aimup;
	float forward = cmd->forwardmove;
	float right = cmd->sidemove;
	float up = cmd->upmove;

	SD_Tools::MathHelper::AngleToVectors(cmd->viewangles, &viewforward, &viewright, &viewup);

	cmd->buttons |= IN_ATTACK;
	cmd->viewangles = GameUtilities::CreateAimAngle(m_Eye, vFinal);

	SD_Tools::MathHelper::AngleToVectors(cmd->viewangles, &aimforward, &aimright, &aimup); 

	SD_Tools::Vector vForwardNorm, vRightNorm, vUpNorm;        
	GameUtilities::AngleNormalize(viewforward, vForwardNorm);  
	GameUtilities::AngleNormalize(viewright, vRightNorm); 
	GameUtilities::AngleNormalize(viewup, vUpNorm); 

	cmd->forwardmove = (aimforward.DotProduct(SD_Tools::MathHelper::MulVector(vForwardNorm, forward)) + aimforward.DotProduct(SD_Tools::MathHelper::MulVector(vRightNorm, right)) + aimforward.DotProduct(SD_Tools::MathHelper::MulVector(vUpNorm, up))); 
	cmd->sidemove = (aimright.DotProduct(SD_Tools::MathHelper::MulVector(vForwardNorm, forward)) + aimright.DotProduct(SD_Tools::MathHelper::MulVector(vRightNorm, right)) + aimright.DotProduct(SD_Tools::MathHelper::MulVector(vUpNorm, up))); 
	cmd->upmove = (aimup.DotProduct(SD_Tools::MathHelper::MulVector(vForwardNorm, forward)) + aimup.DotProduct(SD_Tools::MathHelper::MulVector(vRightNorm, right)) + aimup.DotProduct(SD_Tools::MathHelper::MulVector(vUpNorm, up))); 
	return true;
}

void Aimbot::SetLegitFov( bool Active )
{
	this->LegitFov = Active;
}

void Aimbot::SetLegitSpeed( bool Active )
{
	this->LegitSpeed = Active;
}

void Aimbot::SetFov( float Fov )
{
	this->Fov = Fov;
}

void Aimbot::SetSpeeds( float TickSpeed, float MaxSpeed )
{
	this->TickSpeed = TickSpeed;
	this->MaxSpeed = MaxSpeed;
}
